package edu.uwm.cs552;

import java.awt.*;
import java.awt.event.*;
import java.util.regex.Pattern;
import javax.swing.*;
import java.io.*;

import edu.uwm.cs552.gfx.SVGImageCreator;
import edu.uwm.cs552.util.FormatException;


/**
 * @author Josh Dieringer, Tom Lee
 *
 */
public class HexBoardEditor extends JFrame {

	private static final long serialVersionUID = 1L;
	
	JScrollPane scrollpane;
	HexBoardPanel hexBoardPanel;
	File hexFile;
	
	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {

			@Override
			public void run() {
				HexBoardEditor df = new HexBoardEditor();
				df.setSize(650, 500);
				df.setVisible(true);
			}
		});
	}
	
	public HexBoardEditor() {
		super("Hex Board Editor");
		
		hexFile = null;
		
		//Menu Part
		JMenuItem fileNew = new JMenuItem("New");
		JMenuItem fileOpen = new JMenuItem("Open...");
		JSeparator separator1 = new JSeparator();
		JMenuItem fileSave = new JMenuItem("Save");
		JMenuItem fileSaveAs = new JMenuItem("Save As...");
		JSeparator separator2 = new JSeparator();
		JMenuItem fileQuit = new JMenuItem("Quit");
		
		JMenu file = new JMenu("File");
		file.add(fileNew);
		file.add(fileOpen);
		file.add(separator1);
		file.add(fileSave);
		file.add(fileSaveAs);
		file.add(separator2);
		file.add(fileQuit);
		
		JMenuBar menuBar = new JMenuBar();
		menuBar.add(file);
		this.setJMenuBar(menuBar);

		//Option Part
		Integer[] mags = {10, 15, 20, 30, 50, 75, 100};
		JLabel magnificationLabel = new JLabel("Magnification:");
		final JComboBox<Integer> magnification = new JComboBox<Integer>(mags);
		magnification.setEditable(true);
		final JComboBox<Terrain> terrain = new JComboBox<Terrain>(Terrain.values());
		terrain.setRenderer(new TerrainRenderer());
		final JCheckBox mesh = new JCheckBox();
		JLabel meshLabel = new JLabel("Show Hex Mesh");
		
		JPanel controlPanel = new JPanel();
		controlPanel.add(magnificationLabel);
		controlPanel.add(magnification);
		controlPanel.add(terrain);
		controlPanel.add(mesh);
		controlPanel.add(meshLabel);
		
		//Main Board Part
		hexBoardPanel = new HexBoardPanel(new HexBoard(null,50,25));
		scrollpane = new JScrollPane();
		scrollpane.setViewportView(hexBoardPanel);
		
		Container content = this.getContentPane();
		content.setLayout(new BorderLayout());
		content.add(controlPanel, BorderLayout.NORTH);
		content.add(scrollpane, BorderLayout.CENTER);
		
		// Listeners Part: HexBoardPanel
		final HexSelectListener hexSelectListener = new HexSelectListener();
		hexBoardPanel.addMouseListener(hexSelectListener);
		hexBoardPanel.addMouseMotionListener(hexSelectListener);
		
		// Listeners Part: Frame Quit
		this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
		this.addWindowListener(new WindowAdapter() {

			@Override
			public void windowClosing(WindowEvent e) {
				doQuit();
			}
		});
		
		// Listeners Part: Magnification
		magnification.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				doMagnification(magnification);
			}
		});
		
		// Listeners Part: Terrain
		terrain.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				doTerrain(terrain);
			}
		});
		
		// Listeners Part: Draw Mesh
		mesh.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				doMesh(mesh);
			}
		});
		
		// Listeners Part: Menu Items: New
		fileNew.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				doNew();
			}
		});

		// Listeners Part: Menu Items: Open
		fileOpen.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				doOpen();
			}
		});

		// Listeners Part: Menu Items: Save
		fileSave.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				doSave();
			}
		});

		// Listeners Part: Menu Items: Save As
		fileSaveAs.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				doSaveAs();
			}
		});

		// Listeners Part: Menu Items: Quit
		fileQuit.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				doQuit();
			}
		});
	}

	private void doMagnification(JComboBox<Integer> mag) {
		String s = "10.0";
		double d = 10.0;
		int i = 10;
		
		if(mag.getSelectedItem() instanceof String) {
			s = (String) mag.getSelectedItem();
			String regex = "[-+]?[0-9]*\\.?[0-9]+";
			if(Pattern.matches(regex, s))
				d = Double.parseDouble(s);
			else 
				d = 10.0;
		}
		
		else if(mag.getSelectedItem() instanceof Integer) {
			i = ((Integer) mag.getSelectedItem()).intValue();
			d = (double) i;
		}
		
		if(d < 10.0)
			d = 10.0;
		
		hexBoardPanel.setScale(d);
	}
	
	private void doTerrain(JComboBox<Terrain> terrain) {
		Terrain t = (Terrain) terrain.getSelectedItem();
		hexBoardPanel.setTerrainOnSelected(t);
	}
	
	private void doMesh(JCheckBox m) {
		hexBoardPanel.setDrawMesh(m.isSelected());
	}
	
	private void doNew() {		
		HexBoardDialog hbd = new HexBoardDialog(this);
		hbd.setPreferredSize(new Dimension(300, 200));
		hbd.setResizable(false);
		hbd.pack();
		hbd.setLocationRelativeTo(this);
		hbd.setVisible(true);
		
		try {
			int w = hbd.getTextWidth();
			int h = hbd.getTextHeight();
			HexBoard hb;
			if(hbd.getTextURL() == null)
				hb = new HexBoard(null, w, h);
			else
				hb = new HexBoard(new SVGImageCreator(hbd.getTextURL()), w, h);
			hexBoardPanel = new HexBoardPanel(hb);
			final HexSelectListener hexSelectListener = new HexSelectListener();
			hexBoardPanel.addMouseListener(hexSelectListener);
			hexBoardPanel.addMouseMotionListener(hexSelectListener);
			scrollpane.setViewportView(hexBoardPanel);
		} catch (IOException e) {
			JOptionPane.showMessageDialog(this, "There was a problem loading the URL", "Loading Error", JOptionPane.ERROR_MESSAGE);
		}
		hbd.dispose();
	}
	
	private void doOpen() {
		JFileChooser fc = new JFileChooser();

		int returnVal = fc.showOpenDialog(HexBoardEditor.this);
		if(returnVal == JFileChooser.APPROVE_OPTION) {
			try {
				hexFile = fc.getSelectedFile();
				BufferedReader br = new BufferedReader(new FileReader(hexFile));
				HexBoard board = HexBoard.read(br);
				hexBoardPanel = new HexBoardPanel(board);
				final HexSelectListener hexSelectListener = new HexSelectListener();
				hexBoardPanel.addMouseListener(hexSelectListener);
				hexBoardPanel.addMouseMotionListener(hexSelectListener);
				scrollpane.setViewportView(hexBoardPanel);
				br.close();
				
			} catch (FileNotFoundException e) {
				JOptionPane.showMessageDialog(this, "Could not find specified file", "Loading Error", JOptionPane.ERROR_MESSAGE);
			} catch (NumberFormatException e) {
				JOptionPane.showMessageDialog(this, "The file is not formatted correctly", "Format Error", JOptionPane.ERROR_MESSAGE);
			} catch (FormatException e) {
				JOptionPane.showMessageDialog(this, "The file is not formatted correctly", "Format Error", JOptionPane.ERROR_MESSAGE);
			} catch (IOException e) {
				JOptionPane.showMessageDialog(this, "There was an IO error", "Error", JOptionPane.ERROR_MESSAGE);
			}
		}
	}
	
	private void doSave() {
		try {
			hexBoardPanel.writeHexBoard(hexFile);
		} catch (FileNotFoundException e) {
			doSaveAs();
		}
	}
	
	private void doSaveAs() {
		JFileChooser jfc = new JFileChooser("./");
		
		int returnVal = jfc.showSaveDialog(HexBoardEditor.this);
		if(returnVal == JFileChooser.APPROVE_OPTION) {
			try {
				File file = jfc.getSelectedFile();
				hexBoardPanel.writeHexBoard(file);
				hexFile = file;
			} catch (FileNotFoundException e) {
				JOptionPane.showMessageDialog(this, "Unable to write to file", "Error", JOptionPane.ERROR_MESSAGE);
			}
		}
		
	}
	
	private void doQuit() {
		if(JOptionPane.showConfirmDialog(this, "Are you sure you want to quit?", "Confirm Quit", JOptionPane.WARNING_MESSAGE) == JOptionPane.OK_OPTION)
			System.exit(0);
	}
	
	private class HexSelectListener extends MouseAdapter {

		HexCoordinate lastHexCoordinate = null;
		
		@Override
		public void mousePressed(MouseEvent e) {
			HexCoordinate hexCoordinate = HexCoordinate.fromPoint(e.getPoint(), hexBoardPanel.getScale());
			
			if (!e.isShiftDown()) {
				hexBoardPanel.clearSelected();
			}
			
			hexBoardPanel.toggleSelection(hexCoordinate);
			lastHexCoordinate = hexCoordinate;
		}

		@Override
		public void mouseDragged(MouseEvent e) {
			HexCoordinate hexCoordinate = HexCoordinate.fromPoint(e.getPoint(), hexBoardPanel.getScale());
			
			if (!hexCoordinate.equals(lastHexCoordinate)) {	
				if (e.isShiftDown()) {
					hexBoardPanel.toggleSelection(hexCoordinate);
				}
				else {
					hexBoardPanel.select(hexCoordinate);
				}
			}
			
			lastHexCoordinate = hexCoordinate;
		}
	}
}
